package com.chenfan.mcn.service.impl;

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.chenfan.mcn.config.UserVoContextHolder;
import com.chenfan.mcn.constant.BillCodeCst;
import com.chenfan.mcn.constant.NumberCst;
import com.chenfan.mcn.dao.BrandInfoMapper;
import com.chenfan.mcn.exception.McnErrorCode;
import com.chenfan.mcn.component.CodeGenerateHelper;
import com.chenfan.mcn.model.BrandInfo;
import com.chenfan.mcn.model.dto.BrandInfoQueryDTO;
import com.chenfan.mcn.model.dto.BrandInfoSaveDTO;
import com.chenfan.mcn.model.vo.BrandInfoSelectVO;
import com.chenfan.mcn.service.BrandInfoService;
import com.chenfan.mcn.utils.BusinessAssert;
import com.chenfan.mcn.utils.CommonUtil;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * <p>
 * MCN品牌信息表 服务实现类
 * </p>
 *
 * @author wulg
 * @since 2023-11-02
 */
@Service
public class BrandInfoServiceImpl implements BrandInfoService {

    @Autowired
    private BrandInfoMapper brandInfoMapper;

    @Override
    public Page<BrandInfo> getPage(BrandInfoQueryDTO dto) {
        Page<BrandInfo> dataList = brandInfoMapper.selectPage(new Page<>(dto.getPageNum(), dto.getPageSize()),
                Wrappers.lambdaQuery(BrandInfo.class).eq(BrandInfo::getIsDelete, NumberCst.ZERO)
                        .eq(BrandInfo::getTenantId, UserVoContextHolder.getTenantId())
                        .eq(Objects.nonNull(dto.getStatus()), BrandInfo::getStatus, dto.getStatus())
                        .like(StringUtils.isNotBlank(dto.getBrandCode()), BrandInfo::getBrandCode, dto.getBrandCode())
                        .and(StringUtils.isNotBlank(dto.getBrandName()), (wrapper) -> wrapper.like(BrandInfo::getBrandNameC, dto.getBrandName())
                                .or().like(BrandInfo::getBrandNameE, dto.getBrandName()))
                        .orderByDesc(BrandInfo::getCreateDate)
        );
        return dataList;
    }

    @Override
    public List<BrandInfoSelectVO> search(String keyword, Integer status) {
        List<BrandInfo> dataList = brandInfoMapper.selectList(Wrappers.lambdaQuery(BrandInfo.class)
                        .eq(BrandInfo::getIsDelete, NumberCst.ZERO)
                        .eq(BrandInfo::getTenantId, UserVoContextHolder.getTenantId())
                        .eq(Objects.nonNull(status), BrandInfo::getStatus, status)
                        .and(StringUtils.isNotBlank(keyword), (wrapper) -> wrapper.like(BrandInfo::getBrandNameC, keyword)
                                .or().like(BrandInfo::getBrandNameE, keyword))
                        .last("limit 30")
        );
        return CommonUtil.defaultList(dataList).stream().map(e -> {
            BrandInfoSelectVO brandInfoSelectVO = new BrandInfoSelectVO();
            BeanUtils.copyProperties(e, brandInfoSelectVO);
            return brandInfoSelectVO;
        }).collect(Collectors.toList());
    }

    @Override
    public Long save(BrandInfoSaveDTO dto) {
        BusinessAssert.isTrue(brandInfoMapper.notExist(Wrappers.lambdaQuery(BrandInfo.class)
                .eq(BrandInfo::getBrandNameC, dto.getBrandNameC()).eq(BrandInfo::getIsDelete, NumberCst.ZERO)
                .ne(Objects.nonNull(dto.getId()), BrandInfo::getId, dto.getId())), "品牌中文名称已存在！");
        if(Objects.isNull(dto.getId())) {
            BrandInfo brandInfo = new BrandInfo();
            brandInfo.setBrandCode(CodeGenerateHelper.getCode(BillCodeCst.PP));
            brandInfo.setBrandNameC(dto.getBrandNameC());
            brandInfo.setBrandNameE(dto.getBrandNameE());
            brandInfo.setStatus(ObjectUtils.defaultIfNull(dto.getStatus(), NumberCst.ONE));
            brandInfo.setRemark(dto.getRemark());

            brandInfoMapper.insert(brandInfo);
            return brandInfo.getId();
        }
        BrandInfo entity = this.getBrandInfo(dto.getId());
        BrandInfo updateEntity = new BrandInfo();
        updateEntity.setId(entity.getId());
        updateEntity.setBrandNameC(dto.getBrandNameC());
        updateEntity.setBrandNameE(StringUtils.defaultString(dto.getBrandNameE()));
        updateEntity.setRemark(StringUtils.defaultString(dto.getRemark()));
        updateEntity.setStatus(dto.getStatus());
        brandInfoMapper.updateById(updateEntity);
        return dto.getId();
    }

    @Override
    public Boolean changeStatus(Long id, Integer status) {
        BrandInfo entity = this.getBrandInfo(id);
        BrandInfo updateEntity = new BrandInfo();
        updateEntity.setId(entity.getId());
        updateEntity.setStatus(status);
        return brandInfoMapper.updateById(updateEntity) > 0;
    }

    @Override
    public String getBrandNameByCode(String brandCode) {
        BrandInfo entity = brandInfoMapper.selectOne(Wrappers.lambdaQuery(BrandInfo.class)
                .eq(BrandInfo::getBrandCode, brandCode).eq(BrandInfo::getIsDelete, NumberCst.ZERO));
        if(Objects.isNull(entity)) {
            return brandCode;
        }
        return entity.getBrandNameC();
    }

    @Override
    public Map<String, String> getBrandMapByCodes(List<String> brandCodes) {
        if(CollectionUtils.isEmpty(brandCodes)) {
            return new HashMap<>(0);
        }
        return CommonUtil.defaultList(brandInfoMapper.selectList(Wrappers.lambdaQuery(BrandInfo.class)
                .in(BrandInfo::getBrandCode, brandCodes).eq(BrandInfo::getIsDelete, NumberCst.ZERO))).stream()
                .collect(HashMap::new, (n, o) -> n.putIfAbsent(o.getBrandCode(), o.getBrandNameC()), Map::putAll);
    }

    /**
     *
     * @param id
     * @return
     */
    private BrandInfo getBrandInfo(Long id) {
        BrandInfo entity = brandInfoMapper.selectOne(Wrappers.lambdaQuery(BrandInfo.class)
                .eq(BrandInfo::getId, id).eq(BrandInfo::getIsDelete, NumberCst.ZERO));
        BusinessAssert.notNull(entity, McnErrorCode.DATA_NOT_FOUND);
        return entity;
    }
}
